package cn.iocoder.yudao.module.wms.service.rdrecord08;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
import cn.iocoder.yudao.module.bpm.service.task.ActHiProcinstServiceImpl;
import cn.iocoder.yudao.module.wms.controller.admin.rdrecord08.vo.Rdrecord08PageReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.rdrecord08.vo.Rdrecord08SaveReqVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.rdrecord08.Rdrecord08DO;
import cn.iocoder.yudao.module.wms.dal.dataobject.rdrecord08.Rdrecords08DO;
import cn.iocoder.yudao.module.wms.dal.dataobject.stock.StockDO;
import cn.iocoder.yudao.module.wms.dal.mysql.rdrecord08.Rdrecord08Mapper;
import cn.iocoder.yudao.module.wms.dal.mysql.rdrecord08.Rdrecords08Mapper;
import cn.iocoder.yudao.module.wms.dal.redis.RedisKeyConstants;
import cn.iocoder.yudao.module.wms.dal.redis.serialNumber.WmsSerialNumberRedisDAO;
import cn.iocoder.yudao.module.wms.service.batch.BatchServiceImpl;
import cn.iocoder.yudao.module.wms.service.stock.StockService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.RDRECORD08_NOT_EXISTS;
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.RDRECORDS08_SERIALNUMBER_EXISTS;

/**
 * 其他入库主 Service 实现类
 *
 * @author 曾劲松
 */
@Service
@Validated
public class Rdrecord08ServiceImpl implements Rdrecord08Service {

    /**
     * OA 对应的流程定义 KEY
     */
    public static final String PROCESS_KEY = "rdrecord08-flow";
    @Resource
    private BpmProcessInstanceApi processInstanceApi;
    @Resource
    private Rdrecord08Mapper rdrecord08Mapper;
    @Resource
    private Rdrecords08Mapper rdrecords08Mapper;
    @Resource
    private ActHiProcinstServiceImpl actHiProcinstService;
    @Resource
    private WmsSerialNumberRedisDAO serialNumberRedisDAO;
    @Resource
    private BatchServiceImpl batchService;
    @Resource
    private StockService stockService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createRdrecord08(Rdrecord08SaveReqVO createReqVO) {
        String serialNumber = serialNumberRedisDAO.generate(WmsSerialNumberRedisDAO.RD08_SERIAL_PREFIX, RedisKeyConstants.SERIAL08);
        if (rdrecord08Mapper.selectBySerialNumber(serialNumber) != null) {
            throw exception(RDRECORDS08_SERIALNUMBER_EXISTS);
        }
        // 插入
        Rdrecord08DO rdrecord08 = BeanUtils.toBean(createReqVO, Rdrecord08DO.class,in -> in.setSerialNumber(serialNumber));
        rdrecord08Mapper.insert(rdrecord08);

        for (Rdrecords08DO rdrecords08 : createReqVO.getRdrecords08s()) {
            String batch = batchService.generateBatch(rdrecords08.getInventoryId());
            if (!Objects.equals(batch, "")) {
                rdrecords08.setBatch(batch);
            }
        }
        // 插入子表
        createRdrecords08List(rdrecord08.getId(), createReqVO.getRdrecords08s());
        // 返回
        return rdrecord08.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void process(Long id) {
        // 发起 BPM 流程
        Map<String, Object> processInstanceVariables = new HashMap<>();
        String processInstanceId = processInstanceApi.createProcessInstance(getLoginUserId(),
                new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
                        .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(id)));
        // 将工作流的编号，更新到 业务表单中
        rdrecord08Mapper.updateById(new Rdrecord08DO().setId(id).setProcessInstanceId(processInstanceId).setStatus(BpmTaskStatusEnum.RUNNING.getStatus()));

        //将链接加入到ACT_HI_PROCINST表中
        actHiProcinstService.updateURLById("/inventory/rdrecord08FormInfo?id=" + id,processInstanceId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRdrecord08(Rdrecord08SaveReqVO updateReqVO) {
        // 校验存在
        validateRdrecord08Exists(updateReqVO.getId());
        // 更新
        Rdrecord08DO updateObj = BeanUtils.toBean(updateReqVO, Rdrecord08DO.class);
        rdrecord08Mapper.updateById(updateObj);

        // 更新子表
        updateRdrecords08List(updateReqVO.getId(), updateReqVO.getRdrecords08s());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRdrecord08Status(Long id, Integer status) {
        // 校验存在
        validateRdrecord08Exists(id);
        if (status.equals(BpmTaskStatusEnum.APPROVE.getStatus())) {
            //结束则更新审核人
            rdrecord08Mapper.updateById(new Rdrecord08DO().setId(id).setStatus(status).setAuditor(String.valueOf(getLoginUserId())).setAuditTime(LocalDateTime.now()));
        } else {
            rdrecord08Mapper.updateById(new Rdrecord08DO().setId(id).setStatus(status));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRdrecord08(Long id) {
        // 校验存在
        validateRdrecord08Exists(id);
        // 删除
        rdrecord08Mapper.deleteById(id);

        // 删除子表
        deleteRdrecords08ByOrderId(id);
    }

    private void validateRdrecord08Exists(Long id) {
        if (rdrecord08Mapper.selectById(id) == null) {
            throw exception(RDRECORD08_NOT_EXISTS);
        }
    }

    @Override
    public Rdrecord08DO getRdrecord08(Long id) {
        return rdrecord08Mapper.selectById(id);
    }

    @Override
    public Rdrecord08DO getRdrecord08ByProcessInstanceId(String processInstanceId) {
        return rdrecord08Mapper.selectByProcessInstanceId(processInstanceId);
    }

    @Override
    public PageResult<Rdrecord08DO> getRdrecord08Page(Rdrecord08PageReqVO pageReqVO) {
        return rdrecord08Mapper.selectPage(pageReqVO,getCondition(pageReqVO.getPersonId()),
                getCondition(pageReqVO.getDeptId()),getCondition(pageReqVO.getWarehouseId()),
                getCondition(pageReqVO.getCreator()), getCondition(pageReqVO.getAuditor()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void businessProcessing(Long id, int type) {
        // 校验存在
        validateRdrecord08Exists(id);
        Rdrecord08DO rdrecord08 = rdrecord08Mapper.selectById(id);
        //获取子表信息
        List<Rdrecords08DO> rdrecords08DOList = rdrecords08Mapper.selectListByOrderId(id);
        for (Rdrecords08DO rdrecords08 : rdrecords08DOList) {
            //执行入库方法
            StockDO stockDO = new StockDO().setQty(rdrecords08.getQuantity() * type).setInventoryId(convertInteger(rdrecords08.getInventoryId()))
                    .setWarehouseId(convertInteger(rdrecord08.getWarehouseId())).setLocationId(convertInteger(rdrecords08.getLocationId()))
                    .setBatchCode(rdrecords08.getBatch());
            stockService.store(stockDO);
        }
    }

    // ==================== 子表（其他入库子） ====================

    @Override
    public List<Rdrecords08DO> getRdrecords08ListByOrderId(Long orderId) {
        return rdrecords08Mapper.selectListByOrderId(orderId);
    }

    private void createRdrecords08List(Long orderId, List<Rdrecords08DO> list) {
        list.forEach(o -> o.setOrderId(orderId));
        rdrecords08Mapper.insertBatch(list);
        businessProcessing(orderId,1);
    }

    private void updateRdrecords08List(Long orderId, List<Rdrecords08DO> list) {
        deleteRdrecords08ByOrderId(orderId);
        createRdrecords08List(orderId, list);
    }

    private void deleteRdrecords08ByOrderId(Long orderId) {
        businessProcessing(orderId,-1);
        rdrecords08Mapper.deleteByOrderId(orderId);
    }

    /**
     * 去空转换
     * @param ids id
     * @return id集合
     */
    private Set<String> getCondition(String[] ids) {
        if (ids == null) {
            return Collections.emptySet();
        }
        return new HashSet<>(Arrays.asList(ids));
    }

    /**
     * long转Integer
     * @param param 参数
     * @return Integer
     */
    private Integer convertInteger(Long param) {
        return Integer.valueOf(String.valueOf(param));
    }

}